home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / relay / transmit.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  8KB  |  279 lines

  1. /*
  2.  * transmit - transmit incoming articles to neighbouring machines
  3.  */
  4.  
  5. #include <stdio.h>
  6. #ifndef AMIGA
  7. #  include <sys/types.h>
  8. #endif /* AMIGA */
  9. #include "libc.h"
  10. #include "news.h"
  11. #include "config.h"
  12. #include "headers.h"
  13. #include "active.h"
  14. #include "article.h"
  15. #include "msgs.h"
  16. #include "system.h"
  17. #include "trbatch.h"
  18. #include "transmit.h"
  19.  
  20. /* forwards */
  21. FORWARD boolean oktransmit();
  22. FORWARD void ejaculate(), trappend();
  23.  
  24. /* private */
  25. static boolean debug = NO;
  26.  
  27. void
  28. transdebug(state)
  29. boolean state;
  30. {
  31.     debug = state;
  32. }
  33.  
  34. /*
  35.  * For each system in "sys" other than this one,
  36.  * transmit this article when its ng pattern matches
  37.  * art->h.h_distr (which may be just a copy of art->h.h_ngs).
  38.  */
  39. void
  40. transmit(art, exclude)
  41. register struct article *art;
  42. char *exclude;                    /* no copy to this site */
  43. {
  44.     register struct system *sys;
  45.     register int bsysno = 0;    /* ordinal # of batch sys entry */
  46.  
  47.     rewndsys();
  48.     if (debug)
  49.         (void) fprintf(stderr, "just rewound sys file\n");
  50.     while ((sys = nextsys()) != NULL) {
  51.         if (debug)
  52.             (void) fprintf(stderr,
  53.                 "sy_name=%s sy_ngs=%s sy_distr=%s\n",
  54.                 sys->sy_name, sys->sy_ngs, sys->sy_distr);
  55.         if (oktransmit(art, sys, exclude))
  56.             ejaculate(art, sys, bsysno);
  57.         if (sys->sy_flags&FLG_BATCH)
  58.             ++bsysno;
  59.     }
  60.     if (debug)
  61.         (void) fprintf(stderr, "just finished reading sys file\n");
  62. }
  63.  
  64. /*
  65.  * Is it okay to send the article corresponding to "art" to site "sys",
  66.  * excluding site "exclude"?
  67.  *
  68.  * If L(n) flag is on, must have been posted within n hops of here.
  69.  * Never send to this site, nor the "exclude" site, nor any site with a host
  70.  * in sys->sy_excl named in Path:, nor any site named in Path:.
  71.  *
  72.  * Newsgroups: must match sys's subscription list.
  73.  * Distribution: must match sys's distribution list.  (RFC 850 is wrong:
  74.  * Distribution:s are *not* patterns, they are lists.  See RFC 1036.)
  75.  *
  76.  * If m flag is on, group(s) must be moderated; if u flag is on,
  77.  * must be unmoderated.  (If both are on, act as if neither is on.)
  78.  */
  79. STATIC boolean
  80. oktransmit(art, sys, exclude)
  81. register struct article *art;
  82. register struct system *sys;
  83. char *exclude;                /* no copy to him */
  84. {
  85.     register int flags = sys->sy_flags;
  86.     register char *site = sys->sy_name;
  87.     register char *path =
  88.         canonpath(art->h.h_path, art->h.h_approved, art->h.h_sender);
  89.     register int result;
  90.  
  91.     if (flags&FLG_LOCAL && hopcount(path) > sys->sy_lochops ||
  92.         STREQ(hostname(), site) ||
  93.         exclude != NULL && STREQ(exclude, site) || hostin(site, path) ||
  94.         sys->sy_excl != NULL && anyhostin(sys->sy_excl, path) ||
  95.         !ngmatch(sys->sy_ngs, art->h.h_ngs) ||
  96.         !ngmatch(sys->sy_distr, art->h.h_distr))
  97.         result = NO;
  98.     else if (flags&(FLG_MOD|FLG_UNMOD)) {    /* u, m flag selection */
  99.         if ((flags&(FLG_MOD|FLG_UNMOD)) == (FLG_MOD|FLG_UNMOD))
  100.             result = YES;        /* too silly */
  101.         else
  102.             result = (flags&FLG_MOD? moderated(art->h.h_ngs):
  103.                         !moderated(art->h.h_ngs));
  104.     } else
  105.         result = YES;
  106.     free(path);
  107.     return result;
  108. }
  109.  
  110. /*
  111.  * Send the article denoted by art to the system denoted by sys.
  112.  *
  113.  * When a filename is needed, we use the first one in art->a_files
  114.  * rather than art->a_tmpf because we want a permanent name, and
  115.  * translate it to a full path name to avoid ambiguity.
  116.  *
  117.  * Side-effect: prints the system name on stdout for logging.
  118.  */
  119. STATIC void
  120. ejaculate(art, sys, bsysno)
  121. register struct article *art;
  122. register struct system *sys;
  123. int bsysno;
  124. {
  125.     register char *fullname;    /* sometimes is a message-id */
  126.  
  127.     if (debug)
  128.         (void) fprintf(stderr, "transmitting %s to %s\n",
  129.             art->h.h_msgid, sys->sy_name);
  130.         (void) printf(" %s", sys->sy_name);    /* logging */
  131.     if (sys->sy_flags&FLG_IHAVE)
  132.         fullname = art->h.h_msgid;
  133.     else {
  134.         register char *filename = first(art->a_files);
  135.  
  136.         mkfilenm(filename);
  137.             fullname = fullartfile(filename);
  138.         free(filename);
  139.     }
  140. #ifdef PARANOID
  141.     fullname = strsave(fullname);
  142. #endif
  143.     if (sys->sy_flags&FLG_BATCH)
  144.             trbatch(art, sys, fullname, bsysno);
  145.     else
  146.         trcmd(art, sys, fullname);
  147. #ifdef PARANOID
  148.     free(fullname);
  149. #endif
  150. }
  151.  
  152. /*
  153.  * Execute sys->sy_cmd with the current article as stdin
  154.  * and filename substituted for %s in sys->sy_cmd (if any).
  155.  *
  156.  * Search path includes $NEWSCTL/bin and $NEWSBIN/relay.
  157.  * redirect stdin to prevent consuming my stdin & so cmd's stdin
  158.  * is filename by default.
  159.  *
  160.  * We use strcat instead of sprintf if syscmd contains no %.
  161.  * this avoids the 128-byte restriction on printf output
  162.  * (see printf(3) BUGS, at least in V7).
  163.  */
  164. void
  165. trcmd(art, sys, filename)
  166. struct article *art;
  167. struct system *sys;
  168. char *filename;
  169. {
  170.     register char *cmd;
  171.     int exitstat;
  172.     char *syscmd = sys->sy_cmd, *percent;
  173.     static char *ctlcmd = NULL, *bincmd = NULL;
  174.  
  175.     if (ctlcmd == NULL)
  176.         ctlcmd = strsave(ctlfile("bin"));
  177.     if (bincmd == NULL)
  178.         bincmd = strsave(binfile("relay"));
  179.     cmd = nemalloc((unsigned)(STRLEN("PATH=") + strlen(ctlcmd) +
  180.         STRLEN(":") + strlen(bincmd) + STRLEN(":") + strlen(newspath()) +
  181.         STRLEN(" <") + strlen(filename) + STRLEN(" ") +
  182.         strlen(syscmd) + strlen(filename) + 1));
  183.     (void) strcpy(cmd, "PATH=");
  184.     (void) strcat(cmd, ctlcmd);
  185.     (void) strcat(cmd, ":");
  186.     (void) strcat(cmd, bincmd);
  187.     (void) strcat(cmd, ":");
  188.     (void) strcat(cmd, newspath());
  189.     (void) strcat(cmd, " <");
  190.     (void) strcat(cmd, filename);
  191.     (void) strcat(cmd, " ");
  192.     percent = index(syscmd, '%');
  193.     if (percent == NULL)
  194.         (void) strcat(cmd, syscmd);
  195.     else {
  196.         char *pcent2;
  197.  
  198.         ++percent;
  199.         pcent2 = index(percent, '%');
  200.         if (pcent2 != NULL) {
  201.             art->a_status |= ST_DROPPED;
  202.             (void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
  203.                 progname, cmd);
  204.         } else if (*percent != 's' && *percent != '%') {
  205.             art->a_status |= ST_DROPPED;
  206.             (void) fprintf(stderr, "%s: `%s' contains %%%c, not %%s\n",
  207.                 progname, cmd, *percent);
  208.         } else
  209.             (void) sprintf(cmd+strlen(cmd), syscmd, filename);
  210.     }
  211.     exitstat = system(cmd);
  212.     if (exitstat != 0) {
  213.         art->a_status |= ST_DROPPED;
  214.         (void) fprintf(stderr, "%s: `%s' returned exit status 0%o\n",
  215.             progname, cmd, exitstat);
  216.     }
  217.     free(cmd);
  218. }
  219.  
  220. /*
  221.  * Append "filename" to sys->sy_cmd.  bsysno is the ordinal # of this batch
  222.  * sys line.  If bsysno is low enough, use the batchfile cache of batch file
  223.  * descriptors.
  224.  */
  225. void
  226. trbatch(art, sys, filename, bsysno)
  227. register struct article *art;
  228. struct system *sys;
  229. char *filename;
  230. register int bsysno;
  231. {
  232.     register struct batchfile *bf = bfopen(sys->sy_cmd, bsysno);
  233.  
  234.     if (bf == NULL || bf->bf_str == NULL)
  235.         art->a_status |= ST_DROPPED;
  236.     else {
  237.         trappend(art, sys, bf, filename);
  238.         art->a_status |= bffkclose(bsysno);
  239.     }
  240. }
  241.  
  242. /*
  243.  * write filename, message-id or size on batch file "bf".
  244.  * under the 'f' flag (FLG_SZBATCH), include the size in bytes of the article
  245.  * after "name" to assist the C news batcher.  under the 'n' flag (FLG_NBATCH),
  246.  * write the article's message-id.  afterward, flush "bf" in case
  247.  * the machine crashes before the stream is closed.
  248.  */
  249. STATIC void
  250. trappend(art, sys, bf, name)
  251. register struct article *art;
  252. register struct system *sys;
  253. register struct batchfile *bf;
  254. char *name;
  255. {
  256.     if (fputs(name, bf->bf_str) == EOF)
  257.         fulldisk(art, bf->bf_name);
  258.     if (sys->sy_flags&FLG_SZBATCH &&
  259.         fprintf(bf->bf_str, " %ld", art->a_charswritten) == EOF)
  260.         fulldisk(art, bf->bf_name);
  261.     if (sys->sy_flags&FLG_NBATCH &&
  262.         fprintf(bf->bf_str, " %s", art->h.h_msgid) == EOF)
  263.         fulldisk(art, bf->bf_name);
  264.  
  265.     /* don't check putc return value for portability; use ferror */
  266.     (void) putc('\n', bf->bf_str);
  267.     if (ferror(bf->bf_str) || bfflush(bf) == EOF)
  268.         fulldisk(art, bf->bf_name);        
  269. }
  270.  
  271. /*
  272.  * really close all the open batch files
  273.  */
  274. statust
  275. trclose()
  276. {
  277.     return bfrealclose();
  278. }
  279.